﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

using COUP.Core.Entities;

namespace COUP.Core.Forms
{
    public partial class MapView : Form
    {
        private Color CanWalk = Color.White;
        private Color CantWalk = Color.Black;
        private Bitmap _mapImage;
        private int _selectedMap;

        public Dictionary<int, Map> _maps;
        public bool Display { get; set; }
        public int RefreshRate = 500;

        public MapView(Dictionary<int, Map> Maps)
        {
            CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();

            SetStyle(
                ControlStyles.ResizeRedraw |
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.DoubleBuffer, true);

            _maps = Maps;

            foreach (Map _map in _maps.Values)
            {
                comboBox1.Items.Add(_map._mapID);
            }                       

            Display = true;
        }

        public void SetBackground(Map Target)
        {
            Bitmap MapImage = new Bitmap(Target._width, Target._height, PixelFormat.Format32bppArgb);
            BitmapData MapData = MapImage.LockBits(new Rectangle(0, 0, Target._width, Target._height), ImageLockMode.WriteOnly, MapImage.PixelFormat);

            for (int y = 0; y < MapData.Height; y++)
            {
                IntPtr ptrRowStart = new IntPtr(MapData.Scan0.ToInt32() + MapData.Stride * y);
                for (int x = 0; x < MapData.Width; x++)
                {
                    Color TileColour = Target.CheckMove(new Point(x, y)) ? this.CanWalk : this.CantWalk;

                    Marshal.WriteInt32(new IntPtr(ptrRowStart.ToInt32() + x * 4), TileColour.ToArgb());
                }
            }

            MapImage.UnlockBits(MapData);
            _mapImage = MapImage;
        }

        public void DisplaySectors(Map Target, Graphics e)
        {
            while (!Monitor.TryEnter(Target, 50)) { }

            foreach (iEntity Entity in Target.Query(new Rectangle(0, 0, Target._width, Target._height)))
            {
                if(Entity is Monster)
                    e.DrawRectangle(new Pen(Color.Blue, 1), new Rectangle(Entity.Location, new Size(1, 1)));
                else if (Entity is Character)
                    e.DrawRectangle(new Pen(Color.DarkGreen, 4), new Rectangle(Entity.Location, new Size(1, 1)));
            }

            foreach (Sector Sect in Target.GetSectors(new Rectangle(0, 0, Target._width, Target._height)))
            {
                if(Sect != null)
                    e.DrawRectangle(new Pen(Color.DarkRed, 3), Sect.Bounds);
            }
            Monitor.Exit(Target);
        }

        private void Transform(Graphics e)
        {
            double largestRatio = Math.Max((double)this._mapImage.Width / this.pictureBox1.Width,
                                (double)this._mapImage.Height / this.pictureBox1.Height);
            float posX = (float)(this.pictureBox1.Width * largestRatio / 2 - this._mapImage.Width / 2);
            float posY = (float)(this.pictureBox1.Height * largestRatio / 2 - this._mapImage.Height / 2);
            Matrix mx = new Matrix(1.0f / (float)largestRatio, 0, 0, 1.0f / (float)largestRatio, 0, 0);
            mx.Translate(posX, posY);
            e.Transform = mx;
        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            if (_selectedMap == 0)
                return;

            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            Transform(e.Graphics);
            e.Graphics.DrawImageUnscaled(_mapImage, new Point(0, 0));
            DisplaySectors(_maps[_selectedMap], e.Graphics);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            int MapID = int.Parse(comboBox1.SelectedItem.ToString());
            SetBackground(_maps[MapID]);
            _selectedMap = MapID;
        }

        private void comboBox2_SelectedValueChanged(object sender, EventArgs e)
        {
            if (comboBox2.SelectedItem.ToString() == "Never")
                RefreshRate = Timeout.Infinite;
            else
                RefreshRate = int.Parse(comboBox2.SelectedItem.ToString().Remove(comboBox2.SelectedItem.ToString().Length - 2));
        }
    }
}
